﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using System.Web.Script.Serialization;
using System.Runtime.Serialization.Json;
using System.Xml;
using System.Xml.Serialization;

namespace GuRenFang.Common
{
        /// <summary>
        /// Serialie objct and Deserialize objct
        /// </summary>
        public static class SerializationHelper
        {
            // Store the type of object which being used frequently
            private static Dictionary<int, XmlSerializer> serializerDictionary = new Dictionary<int, XmlSerializer>();

            /// <summary>
            /// Get serializer by type
            /// </summary>
            /// <param name="parameter">the type of object</param>
            /// <returns>a XmlSerializer</returns>
            /// Change History
            /// Date                Changer             Description
            /// ---                 ---                 ---
            public static XmlSerializer GetSerializer(Type type)
            {
                int typeHashCode = type.GetHashCode();

                if (!serializerDictionary.ContainsKey(typeHashCode))
                    serializerDictionary.Add(typeHashCode, new XmlSerializer(type));

                return serializerDictionary[typeHashCode];
            }

            #region Serialize and deserialize between string and object
            /// <summary>
            /// Get a string which is serialized with a object
            /// </summary>
            /// <param name="obj">the object which want to be serialized</param>
            /// <returns>a string</returns>
            /// Change History
            /// Date                Changer             Description
            /// ---                 ---                 ---
            public static string Serialize(object obj)
            {
                string returnStr = "";
                XmlSerializer serializer = GetSerializer(obj.GetType());
                MemoryStream memoryStream = new MemoryStream();
                XmlTextWriter xmlTextWriter = null;
                StreamReader streamReader = null;

                try
                {
                    xmlTextWriter = new System.Xml.XmlTextWriter(memoryStream, Encoding.UTF8);
                    xmlTextWriter.Formatting = System.Xml.Formatting.Indented;
                    serializer.Serialize(xmlTextWriter, obj);
                    memoryStream.Seek(0, SeekOrigin.Begin);
                    streamReader = new StreamReader(memoryStream);
                    returnStr = streamReader.ReadToEnd();
                }
                finally
                {
                    if (xmlTextWriter != null)
                        xmlTextWriter.Close();
                    if (streamReader != null)
                        streamReader.Close();
                    memoryStream.Close();
                }

                return returnStr;
            }

            /// <summary>
            /// Deserialize a object from a serialized string
            /// </summary>
            /// <typeparam name="T">the type of the object</typeparam>
            /// <param name="serializedString">the serialized string</param>
            /// <returns>an object</returns>
            /// Change History
            /// Date                Changer             Description
            /// ---                 ---                 ---
            public static T Deserialize<T>(string serializedString)
            {
                byte[] bytes = Encoding.UTF8.GetBytes(serializedString);
                XmlSerializer serializer = GetSerializer(typeof(T));
                if (serializer != null)
                {
                    return (T)serializer.Deserialize(new MemoryStream(bytes));
                }
                else
                {
                    return default(T);
                }
            }
            #endregion

            #region Serialize and deserialize between a xml file and object
            /// <summary>
            /// Serialize an object to a xml file
            /// </summary>
            /// <param name="obj">the object which want to be serialized</param>
            /// <param name="filename">the path of the file</param>
            /// <returns>is it successful</returns>
            public static bool SerializeToFile(object obj, string filename)
            {
                bool isSuccess = false;

                if (obj != null && File.Exists(filename))
                {
                    FileStream fileStream = null;

                    try
                    {
                        fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                        XmlSerializer serializer = GetSerializer(obj.GetType());
                        serializer.Serialize(fileStream, obj);
                        isSuccess = true;
                    }
                    finally
                    {
                        if (fileStream != null)
                            fileStream.Close();
                    }
                }

                return isSuccess;
            }

            /// <summary>
            /// Deserialize an object from a xml file
            /// </summary>
            /// <typeparam name="T">the type of the object</typeparam>
            /// <param name="filename">the path of the file</param>
            /// <returns>an object</returns>
            public static T DeserializeFromFile<T>(string filename)
            {
                FileStream fileStream = null;
                try
                {
                    fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                    XmlSerializer serializer = GetSerializer(typeof(T));
                    if (serializer != null)
                    {
                        return (T)serializer.Deserialize(fileStream);
                    }
                    else
                    {
                        return default(T);
                    }
                }
                finally
                {
                    if (fileStream != null)
                        fileStream.Close();
                }
            }
            #endregion

            #region deserialize between json and object
            public static T DeserializeJson<T>(string json)
            {
                var  jss = new JavaScriptSerializer();
                return jss.Deserialize<T>(json);
            }

            
            public static string SerializeToJson<T>(T obj)
            {
                var jss = new JavaScriptSerializer();
                return jss.Serialize(obj);
            }
            #endregion

            public static string DataTable2Json(DataTable dtb)
            {
                JavaScriptSerializer jss = new JavaScriptSerializer();
                ArrayList dic = new ArrayList();
                foreach (DataRow row in dtb.Rows)
                {
                    Dictionary<string, object> drow = new Dictionary<string, object>();
                    foreach (DataColumn col in dtb.Columns)
                    {
                        drow.Add(col.ColumnName, row[col.ColumnName]);
                    }
                    dic.Add(drow);
                }
                return jss.Serialize(dic);
            }

            public static DataTable Json2DataTable(string json)
            {
                JavaScriptSerializer jss = new JavaScriptSerializer();
                ArrayList dic = jss.Deserialize<ArrayList>(json);
                DataTable dtb = new DataTable();
                if (dic.Count > 0)
                {
                    foreach (Dictionary<string, object> drow in dic)
                    {
                        if (dtb.Columns.Count == 0)
                        {
                            foreach (string key in drow.Keys)
                            {
                                dtb.Columns.Add(key, drow[key].GetType());
                            }
                        }
                        DataRow row = dtb.NewRow();
                        foreach (string key in drow.Keys)
                        {
                            row[key] = drow[key];
                        }
                        dtb.Rows.Add(row);
                    }
                }
                return dtb;
            }


            /// <summary>
            /// 生成Json格式
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="obj"></param>
            /// <returns></returns>
            public static string GetJson<T>(T obj)
            {
                DataContractJsonSerializer json = new DataContractJsonSerializer(obj.GetType());
                using (MemoryStream stream = new MemoryStream())
                {
                    json.WriteObject(stream, obj);

                    string szJson = Encoding.UTF8.GetString(stream.ToArray()); return szJson;
                }
            }

            /// <summary>
            /// 获取Json的Model
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="szJson"></param>
            /// <returns></returns>
            public static T ParseFromJson<T>(string szJson)
            {
                T obj = Activator.CreateInstance<T>();
                using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(szJson)))
                {
                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
                    return (T)serializer.ReadObject(ms);
                }
            }
        }
    }